#ifndef VECTORMATH_H
#define VECTORMATH_H

#include <math.h>

const double pi = 3.1415926535897932384626433832795;

class Vector3
{
private:
    double x;
    double y;
    double z;
public:
    Vector3(){}                                                //Конструктор. Пустой. Ничего не делает.
    Vector3(const Vector3 &V)
    {
        x = V.x;
        y = V.y;
        z = V.z;
    }

    /*Vector3(int New_x, double New_y, double New_z)
    {
        x = New_x;
        y = New_y;
        z = New_z;
    }                                                 //Конструктор. Пустой. Ничего не делает.
    Vector3(double New_x, int New_y, double New_z)
    {
        x = New_x;
        y = New_y;
        z = New_z;
    }                                                 //Конструктор. Пустой. Ничего не делает.
    Vector3(double New_x, double New_y, int New_z)
    {
        x = New_x;
        y = New_y;
        z = New_z;
    }*/                                                  //Конструктор. Пустой. Ничего не делает.
    Vector3(double New_x, double New_y, double New_z)
    {
        x = New_x;
        y = New_y;
        z = New_z;
    }                                                           //Конструктор. Задает начальные значения вектора как 3 координаты.
    /*Vector3(double *New_x, double New_y, double New_z)
    {
        x = *New_x;
        y = New_y;
        z = New_z;
    }
    Vector3(double New_x, double *New_y, double New_z)
    {
        x = New_x;
        y = *New_y;
        z = New_z;
    }
    Vector3(double New_x, double New_y, double *New_z)
    {
        x = New_x;
        y = New_y;
        z = *New_z;
    }
    Vector3(double New_x, double *New_y, double *New_z)
    {
        x = New_x;
        y = *New_y;
        z = *New_z;
    }
    Vector3(double *New_x, double New_y, double *New_z)
    {
        x = *New_x;
        y = New_y;
        z = *New_z;
    }
    Vector3(double *New_x, double *New_y, double New_z)
    {
        x = *New_x;
        y = *New_y;
        z = New_z;
    }
    Vector3(double *New_x, double *New_y, double *New_z)
    {
        x = *New_x;
        y = *New_y;
        z = *New_z;
    }*/

   /* Vector3(Vector3 &New_V)
    {
        x = New_V.x;
        y = New_V.y;
        z = New_V.z;
    }*/

    Vector3(Vector3 &New_V)
    {
        x = New_V.x;
        y = New_V.y;
        z = New_V.z;
    }

    /*Vector3(Vector3 *New_V)
    {
        x = New_V->x;
        y = New_V->y;
        z = New_V->z;
    } */                                                          //Конструктор. Задает вектор, как копию другого вектора.

    void set(double New_x, double New_y, double New_z)
    {
        x = New_x;
        y = New_y;
        z = New_z;
    }                                                           //Задает вектор в координатном виде.
    /*void set(double *New_x, double New_y, double New_z)
    {
        x = *New_x;
        y = New_y;
        z = New_z;
    }
    void set(double New_x, double *New_y, double New_z)
    {
        x = New_x;
        y = *New_y;
        z = New_z;
    }
    void set(double New_x, double New_y, double *New_z)
    {
        x = New_x;
        y = New_y;
        z = *New_z;
    }
    void set(double New_x, double *New_y, double *New_z)
    {
        x = New_x;
        y = *New_y;
        z = *New_z;
    }
    void set(double *New_x, double New_y, double *New_z)
    {
        x = *New_x;
        y = New_y;
        z = *New_z;
    }
    void set(double *New_x, double *New_y, double New_z)
    {
        x = *New_x;
        y = *New_y;
        z = New_z;
    }
    void set(double *New_x, double *New_y, double *New_z)
    {
        x = *New_x;
        y = *New_y;
        z = *New_z;
    }*/

    void setX(double New_x){x = New_x;}                         //Устанавливает X-овую состовляющую вектора.
    //void setX(double *New_x){x = *New_x;}
    void setY(double New_y){y = New_y;}                         //Устанавливает Y-овую состовляющую вектора.
    //void setY(double *New_y){y = *New_y;}
    void setZ(double New_z){z = New_z;}                         //Устанавливает Z-овую состовляющую вектора.
    //void setZ(double *New_z){z = *New_z;}

    double getX() const {return x;}                                    //Возвращает X-овую состовляющую вектора.
    double getY() const {return y;}                                    //Возвращает Y-овую состовляющую вектора.
    double getZ() const {return z;}                                    //Возвращает Z-овую состовляющую вектора.
    double getLength() const {return sqrt(x * x + y * y + z * z);}     //Возвращает длину вектора.

    Vector3 normalize();
    friend Vector3 vector_normalize(Vector3 V);
    //friend Vector3 Vector3_normalize(Vector3 *V);
    Vector3 rotateGrad(Vector3 V2, double angle);               //Поворачивает вектор к вектору V2 на угол angle.
    //Vector3 rotateGrad(Vector3 *V2, double angle);
    friend Vector3 vector_rotateGrad(Vector3 V1, Vector3 V2, double angle);
    //friend Vector3 Vector3_rotateGrad(Vector3 *V1, Vector3 V2, double angle);
    //friend Vector3 Vector3_rotateGrad(Vector3 V1, Vector3 *V2, double angle);
    //friend Vector3 Vector3_rotateGrad(Vector3 *V1, Vector3 *V2, double angle);
    Vector3 rotateRad(Vector3 V2, double angle);                //Поворачивает вектор к вектору V2 на угол angle.
    //Vector3 rotateRad(Vector3 *V2, double angle);
    friend Vector3 vector_rotateRad(Vector3 V1, Vector3 V2, double angle);
    //friend Vector3 Vector3_rotateRad(Vector3 *V1, Vector3 V2, double angle);
    //friend Vector3 Vector3_rotateRad(Vector3 V1, Vector3 *V2, double angle);
    //friend Vector3 Vector3_rotateRad(Vector3 *V1, Vector3 *V2, double angle);

    Vector3 operator = (Vector3 V);                             //Перегрузка оператора '='. Присваивает первому вектору значения второго. Возвращает конечное значение первого вектора.
    //Vector3 operator = (Vector3 *V);
    //friend Vector3 operator = (Vector3 *V1, Vector3 V2);
    Vector3 operator += (Vector3 V);                            //Перегрузка оператора '+='. Кладет сумму векторов в первый вектор. Возвращает конечное значение первого вектора.
    //Vector3 operator += (Vector3 *V);
    Vector3 operator += (double R);                             //Перегрузка оператора '+='. Удлинняет вектор на R. Возвращает конечное значение первого вектора.
    //Vector3 operator += (double *R);
    Vector3 operator -= (Vector3 V);                            //Перегрузка оператора '-='. Кладет разность векторов в первый вектор. Возвращает конечное значение первого вектора.
    //Vector3 operator -= (Vector3 *V);
    Vector3 operator -= (double R);                             //Перегрузка оператора '-='. Укорачивает вектор на R. Если длинна вектора меньше R, то результирующий вектор будет направлен в обратную сторону. Возвращает конечное значение первого вектора.
    //Vector3 operator -= (double *R);
    Vector3 operator *= (Vector3 V);                            //Перегрузка оператора '*='. Кладет результат векторного произведения в первый вектор. Возвращает конечное значение первого вектора.
    //Vector3 operator *= (Vector3 *V);
    Vector3 operator *= (double R);                             //Перегрузка оператора '*='. Увеличивает длину вектора в R раз. Возвращает конечное значение первого вектора.
    //Vector3 operator *= (double *R);
    Vector3 operator /= (double R);                             //Перегрузка оператора '/='. Уменьшает длину вектора в R раз. Возвращает конечное значение первого вектора.
    //Vector3 operator /= (double *R);
    Vector3 operator + (Vector3 V);                             //Перегрузка оператора '+'. Сумма векторов. Возвращает результирующий вектор.
    //Vector3 operator + (Vector3 *V);
    //friend Vector3 operator + (Vector3 *V1, Vector3 V2);
    Vector3 operator + (double R);                              //Перегрузка оператора '+'. Удлиннение вектора на R. Возвращает результирующий вектор.
    //Vector3 operator + (double *R);
    Vector3 operator - (Vector3 V);                             //Перегрузка оператора '-'. Разность векторов. Возвращает результирующий вектор.
    //Vector3 operator - (Vector3 *V);
    //friend Vector3 operator - (Vector3 *V1, Vector3 V2);
    Vector3 operator - (double R);                              //Перегрузка оператора '-'. Укорачивание вектора. Если длинна вектора меньше R, то результирующий вектор будет направлен в обратную сторону. Возвращает результирующий вектор.
    //Vector3 operator - (double *R);
    Vector3 operator - ();                                      //Перегрузка оператора '-'. Разность векторов. Возвращает вектор, направленый в противоположную сторону той же длинны.
    Vector3 operator * (Vector3 V);                             //Перегрузка оператора '*'. Векторное произведение векторов. Возвращает результирующий вектор.
    //Vector3 operator * (Vector3 *V);
    //friend Vector3 operator * (Vector3 *V1, Vector3 V2);
    Vector3 operator * (double R);                              //Перегрузка оператора '*'. Удлиннение вектора в R раз. Возвращает результирующий вектор.
    //Vector3 operator * (double *R);
    Vector3 operator / (double R);                              //Перегрузка оператора '/'. Укорачивание вектора в R раз. Возвращает результирующий вектор.
    //Vector3 operator / (double *R);
    double operator % (Vector3 V);                              //Перегрузка оператора '%'. Скалярное произведение векторов. Возвращает результирующий вектор.
    //double operator % (Vector3 *V);
    //friend Vector3 operator % (Vector3 *V1, Vector3 V2);

    int operator == (Vector3 V);                                //Перегрузка оператора '=='. Проверка на равность. Возвращает число от 0 до 7.
                                                                //Если перевести возвращенное число в двоичную систему исчисления,
                                                                //то первый бит - результат проверки на равность X-овых состовляющих, второй бит - Y-овых, третий Z-овых.
    //int operator == (Vector3 *V);
    //friend int operator == (Vector3 *V1, Vector3 V2);
    int operator != (Vector3 V);                                //Перегрузка оператора '!='. Проверка на неравность. Возвращает либо 1(не равны), либо 0(равны).
    //int operator != (Vector3 *V);
    //friend int operator != (Vector3 *V1, Vector3 V2);

};
Vector3 vector3_normalize(Vector3 V);
Vector3 vector3_rotateGrad(Vector3 V1, Vector3 V2, double angle);
Vector3 vector3_rotateRad(Vector3 V1, Vector3 V2, double angle);

#endif // VECTORMATH_H
